package com.witmore.neutron.ai.web.wechat.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jk.common.response.ResponseResult;
import com.witmore.neutron.ai.db.entity.ScorpionTradingUserDO;
import com.witmore.neutron.ai.db.entity.UserDO;
import com.witmore.neutron.ai.db.mapper.ScorpionTradingUserMapper;
import com.witmore.neutron.ai.db.mapper.UserMapper;
import com.witmore.neutron.ai.web.controller.vo.UserSession;
import com.witmore.neutron.ai.web.service.UserBindResult;
import com.witmore.neutron.ai.web.service.UserService;
import com.witmore.neutron.ai.web.websocket.WebSocketService;
import com.witmore.neutron.ai.web.wechat.config.WechatAutoReplyConfig;
import com.witmore.neutron.ai.web.wechat.dto.WechatCallbackMessage;
import com.witmore.neutron.ai.web.wechat.dto.WechatUserInfo;
import com.witmore.neutron.ai.web.wechat.service.WechatCallbackService;
import com.witmore.neutron.ai.web.wechat.service.WechatOAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信回调服务实现类
 * Author: 豆子高
 * Date: 2025/12/19
 */
@Slf4j
@Service
public class WechatCallbackServiceImpl implements WechatCallbackService {

    @Autowired
    private ScorpionTradingUserMapper scorpionTradingUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private WebSocketService webSocketService;

    @Autowired
    private WechatAutoReplyConfig autoReplyConfig;

    @Autowired
    private WechatOAuthService wechatOAuthService;

    private static final String SUBSCRIBE_CACHE_PREFIX = "wechat:subscribe:";

    @Override
    public String handleCallback(WechatCallbackMessage message) {
        try {
            log.info("收到微信回调消息：{}", message);

            if ("event".equals(message.getMsgType())) {
                if ("subscribe".equals(message.getEvent())) {
                    // 关注事件 - 异步处理绑定逻辑，立即返回欢迎消息
                    return handleSubscribeEventQuick(message);
                } else if ("SCAN".equals(message.getEvent())) {
                    // 已关注用户扫码事件
                    log.info("已关注用户扫码，OpenID：{}，EventKey：{}", message.getFromUserName(), message.getEventKey());
                    return handleScanEventQuick(message);
                }
            }
            return "success";
        } catch (Exception e) {
            log.error("处理微信回调消息异常", e);
            // 异常时必须返回success，避免微信重试
            return "success";
        }
    }

    @Override
    public boolean handleSubscribeEvent(String openId, String eventKey, String ticket) {
        try {
            // 保存关注信息到Redis缓存，等待用户输入手机号
            String cacheKey = SUBSCRIBE_CACHE_PREFIX + openId;
            redisTemplate.opsForValue().set(cacheKey, eventKey, 30, TimeUnit.MINUTES);

            log.info("用户关注成功，OpenID：{}，EventKey：{}", openId, eventKey);
            return true;
        } catch (Exception e) {
            log.error("处理关注事件异常，OpenID：{}", openId, e);
            return false;
        }
    }

    @Override
    public boolean saveUserInfo(String openId, String phone, String sceneStr) {
        try {
            // 先根据手机号查询用户是否已存在
            ScorpionTradingUserDO existingUserByPhone = scorpionTradingUserMapper.selectOne(
                    new LambdaQueryWrapper<ScorpionTradingUserDO>()
                            .eq(ScorpionTradingUserDO::getPhone, phone)
                            .eq(ScorpionTradingUserDO::getIsDeleted, 0)
            );

            if (existingUserByPhone != null) {
                // 如果通过手机号找到了用户，更新其openid
                existingUserByPhone.setOpenid(openId);
                existingUserByPhone.setUpdateTime(LocalDateTime.now());
                scorpionTradingUserMapper.updateById(existingUserByPhone);
                log.info("根据手机号找到已有用户，更新OpenID成功，用户ID：{}，手机号：{}，OpenID：{}",
                        existingUserByPhone.getId(), phone, openId);
                return true;

            } else {
                // 如果手机号不存在，再检查openid是否已存在
                ScorpionTradingUserDO existingUserByOpenId = scorpionTradingUserMapper.selectOne(
                        new LambdaQueryWrapper<ScorpionTradingUserDO>()
                                .eq(ScorpionTradingUserDO::getOpenid, openId)
                                .eq(ScorpionTradingUserDO::getIsDeleted, 0)
                );

                if (existingUserByOpenId != null) {
                    // 如果openid已存在，更新手机号
                    existingUserByOpenId.setPhone(phone);
                    existingUserByOpenId.setUpdateTime(LocalDateTime.now());
                    scorpionTradingUserMapper.updateById(existingUserByOpenId);
                    log.info("根据OpenID找到已有用户，更新手机号成功，用户ID：{}，OpenID：{}，手机号：{}",
                            existingUserByOpenId.getId(), openId, phone);
                } else {
                    // 都不存在，创建新用户
                    ScorpionTradingUserDO newUser = new ScorpionTradingUserDO();
                    newUser.setOpenid(openId);
                    newUser.setPhone(phone);
                    newUser.setUserName("微信用户_" + phone);
                    newUser.setCreateTime(LocalDateTime.now());
                    newUser.setUpdateTime(LocalDateTime.now());
                    newUser.setIsDeleted((byte) 0);

                    scorpionTradingUserMapper.insert(newUser);
                    log.info("创建新用户成功，OpenID：{}，手机号：{}", openId, phone);
                }
            }

            // 通过WebSocket推送结果给前端
            Map<String, Object> map = new HashMap<>();
            map.put("openId", openId);
            map.put("phone", phone);
            webSocketService.sendMessageToScene(sceneStr, JSONObject.toJSONString(map));

            return true;
        } catch (Exception e) {
            log.error("保存用户信息异常，OpenID：{}，手机号：{}", openId, phone, e);
            return false;
        }
    }

    /**
     * 快速处理关注事件 - 立即返回欢迎消息，异步处理绑定逻辑
     */
    private String handleSubscribeEventQuick(WechatCallbackMessage message) {
        String openId = message.getFromUserName();
        String eventKey = message.getEventKey();
        String ticket = message.getTicket();
        try {
            log.info("快速处理关注事件，OpenID：{}，EventKey：{}", openId, eventKey);

            // 异步处理绑定逻辑
            processSubscribeEventAsync(openId, eventKey, ticket);

            // 立即返回统一的欢迎消息
            return buildAutoReplyMessage(message, WechatAutoReplyConfig.WELCOME_MESSAGE);

        } catch (Exception e) {
            log.error("快速处理关注事件异常，OpenID：{}", openId, e);
            return buildAutoReplyMessage(message, WechatAutoReplyConfig.WELCOME_MESSAGE);
        }
    }

    /**
     * 快速处理已关注用户扫码事件
     */
    private String handleScanEventQuick(WechatCallbackMessage message) {
        String openId = message.getFromUserName();
        String eventKey = message.getEventKey();
        try {
            log.info("快速处理扫码事件，OpenID：{}，EventKey：{}", openId, eventKey);
            // 多场景处理
            if (eventKey.contains("_ai_")) {
                // 异步处理绑定逻辑
                processScanEventAsync(openId, eventKey);

                // 立即返回感谢消息
                return buildAutoReplyMessage(message, WechatAutoReplyConfig.SCAN_MESSAGE);
            } else if (eventKey.contains("app_login")) {
                // 扫码登录 （登录场景 app_login_xxxx_0 、绑定场景 app_login_xxxx_userid）
                // 取eventKey最后一个下划线后面的参数
                String userId = eventKey.substring(eventKey.lastIndexOf("_") + 1);
                if (userId.equals("0")) {
                    WechatUserInfo wechatUserInfo = new WechatUserInfo();
                    wechatUserInfo.setOpenid(openId);
                    UserDO userDO = wechatOAuthService.processWechatLogin(wechatUserInfo);
                    // 通过WebSocket推送结果给前端
                    Map<String, Object> map = new HashMap<>();
                    UserSession userSession = userService.setUserSession(userDO);
                    map.put("token", userSession.getToken());
                    webSocketService.sendMessageToScene(eventKey, JSONObject.toJSONString(ResponseResult.success(map)));
                } else {
                    // openid与用户信息绑定逻辑
                    try {
                        boolean bindResult = bindOpenidToUser(openId, userId);
                        if (bindResult) {
                            log.info("微信openid绑定成功，userId: {}, openId: {}", userId, openId);
                            webSocketService.sendMessageToScene(eventKey, JSONObject.toJSONString(ResponseResult.success("bindSuccess")));
                        } else {
                            log.warn("微信openid绑定失败，userId: {}, openId: {}", userId, openId);
                            webSocketService.sendMessageToScene(eventKey, JSONObject.toJSONString(ResponseResult.fail(500, "绑定失败")));
                        }
                    } catch (Exception e) {
                        log.error("微信openid绑定异常，userId: {}, openId: {}", userId, openId, e);
                        webSocketService.sendMessageToScene(eventKey, JSONObject.toJSONString(ResponseResult.fail(500, e.getMessage())));
                    }
                }
                return "success";

            } else {
                // TODO 其他场景
                return buildAutoReplyMessage(message, WechatAutoReplyConfig.SCAN_MESSAGE);
            }


        } catch (Exception e) {
            log.error("快速处理扫码事件异常，OpenID：{}", openId, e);
            return buildAutoReplyMessage(message, WechatAutoReplyConfig.SCAN_MESSAGE);
        }
    }

    /**
     * 异步处理关注事件的绑定逻辑
     */
    @Async
    public void processSubscribeEventAsync(String openId, String eventKey, String ticket) {
        try {
            log.info("异步处理关注事件绑定逻辑，OpenID：{}，EventKey：{}", openId, eventKey);

            // 提取场景值（去掉qrscene_前缀）
            String sceneStr = eventKey != null && eventKey.startsWith("qrscene_") ? eventKey.substring(8) : eventKey;

            // 从场景值中提取手机号
            String phone = extractPhoneFromSceneStr(sceneStr);

            if (phone != null && isPhoneNumber(phone)) {
                // 直接保存用户信息
                boolean success = saveUserInfo(openId, phone, sceneStr);
                log.info("异步绑定结果，OpenID：{}，手机号：{}，成功：{}", openId, phone, success);
            } else {
                // 如果无法提取手机号，则保存关注信息等待用户输入
                handleSubscribeEvent(openId, eventKey, ticket);
            }

        } catch (Exception e) {
            log.error("异步处理关注事件异常，OpenID：{}", openId, e);
        }
    }

    /**
     * 异步处理扫码事件的绑定逻辑
     */
    @Async
    public void processScanEventAsync(String openId, String eventKey) {
        try {
            log.info("异步处理扫码事件绑定逻辑，OpenID：{}，EventKey：{}", openId, eventKey);

            // 提取场景值
            String sceneStr = eventKey != null && eventKey.startsWith("qrscene_") ? eventKey.substring(8) : eventKey;

            // 从场景值中提取手机号
            String phone = extractPhoneFromSceneStr(sceneStr);

            if (phone != null && isPhoneNumber(phone)) {
                // 直接保存用户信息
                boolean success = saveUserInfo(openId, phone, sceneStr);
                log.info("异步扫码绑定结果，OpenID：{}，手机号：{}，成功：{}", openId, phone, success);
            }

        } catch (Exception e) {
            log.error("异步处理扫码事件异常，OpenID：{}", openId, e);
        }
    }

    /**
     * 构建自动回复消息
     */
    private String buildAutoReplyMessage(WechatCallbackMessage message, String content) {
        if (!autoReplyConfig.isEnabled()) {
            return "success";
        }

        // 如果禁用表情符号，则移除表情
        if (!autoReplyConfig.isEnableEmoji()) {
            content = content.replaceAll("[🎉📈💬📊📱]", "");
        }

        return buildReplyMessage(message, content);
    }


    /**
     * 从场景值中提取手机号
     * 场景值格式：15088723425_c775a593
     *
     * @param sceneStr 场景值
     * @return 手机号，如果无法提取则返回null
     */
    private String extractPhoneFromSceneStr(String sceneStr) {
        if (!StringUtils.hasText(sceneStr)) {
            return null;
        }

        try {
            // 按下划线分割，取第一部分作为手机号
            String[] parts = sceneStr.split("_");
            if (parts.length >= 1) {
                String possiblePhone = parts[0];
                // 简单验证一下是否是手机号格式
                if (possiblePhone.matches("^1[3-9]\\d{9}$")) {
                    return possiblePhone;
                }
            }
        } catch (Exception e) {
            log.error("解析场景值异常，sceneStr：{}", sceneStr, e);
        }

        return null;
    }


    /**
     * 验证手机号格式
     */
    private boolean isPhoneNumber(String content) {
        return StringUtils.hasText(content) && content.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 构建回复消息
     */
    private String buildReplyMessage(WechatCallbackMessage message, String content) {
        long timestamp = System.currentTimeMillis() / 1000;
        return String.format(
                "<xml>" +
                        "<ToUserName><![CDATA[%s]]></ToUserName>" +
                        "<FromUserName><![CDATA[%s]]></FromUserName>" +
                        "<CreateTime>%d</CreateTime>" +
                        "<MsgType><![CDATA[text]]></MsgType>" +
                        "<Content><![CDATA[%s]]></Content>" +
                        "</xml>",
                message.getFromUserName(), message.getToUserName(), timestamp, content
        );

    }

    /**
     * 根据userId绑定微信openid
     *
     * @param openId 微信openid
     * @param userId 用户ID
     * @return 绑定是否成功
     */
    private boolean bindOpenidToUser(String openId, String userId) {
        try {
            // 验证参数
            if (!StringUtils.hasText(openId) || !StringUtils.hasText(userId)) {
                log.warn("绑定参数不能为空，openId: {}, userId: {}", openId, userId);
                return false;
            }

            // 转换userId为整数
            int userIdInt;
            try {
                userIdInt = Integer.parseInt(userId);
            } catch (NumberFormatException e) {
                log.warn("userId格式不正确: {}", userId);
                return false;
            }

            // 查询目标用户是否存在
            UserDO targetUser = userMapper.selectById(userIdInt);
            if (targetUser == null) {
                log.warn("用户不存在，userId: {}", userId);
                return false;
            }

            // 使用UserService的公共绑定方法
            WechatUserInfo wechatUserInfo = new WechatUserInfo();
            wechatUserInfo.setOpenid(openId);
            UserBindResult bindResult = userService.bindUserOpenid(targetUser, wechatUserInfo);

            if (bindResult.isSuccess()) {
                log.info("微信openid绑定成功，userId: {}, openId: {}, message: {}", userId, openId, bindResult.getMessage());
                return true;
            } else {
                log.warn("微信openid绑定失败，userId: {}, openId: {}, message: {}", userId, openId, bindResult.getMessage());
                return false;
            }

        } catch (Exception e) {
            log.error("绑定微信openid异常，userId: {}, openId: {}", userId, openId, e);
            return false;
        }
    }
}
